/**
 * @Author: 陈瑞鹏
 * @Date:   2022-11-25 11:25:14
 * @Last Modified by:   陈瑞鹏
 * @Last Modified time: 2023-02-01 10:27:43
 */
import aiCtr from "../ctrs/aiCtr";
import bagCtr from "../ctrs/bags/bagCtr";
import barrackCtr from "../ctrs/barracks/barrackCtr";
import barrackEntity from "../ctrs/barracks/barrackEntity";
import gameCtr, { modelType } from "../ctrs/gameCtr";
import helpCtr from "../ctrs/helps/helpCtr";
import pvpCtr from "../ctrs/pvp/pvpCtr";
import robotPvpCtr from "../ctrs/pvp/robotPvpCtr";
import { SoundResManager } from "../ctrs/soundCtr";
import { createFlyTxt } from "../libs/core/utils";
import { gameConfig } from "../shared/game/gameConfig";
import { BaseState } from "../shared/game/state/BaseState";
import { ResState } from "../shared/game/state/ResState";
import { TweenPool } from "../utils/TweenPool";
import circleEle from "./circleEle";
import frozenEle from "./frozenEle";
import lineCom from "./lineCom";
import squareCom from "./squareCom";
import triangleCom from "./triangleCom";

/**
 * @Author: 陈瑞鹏
 * @Date:   2022-11-25 11:25:14
 * @Last Modified by:   陈瑞鹏
 * @Last Modified time: 2022-11-30 17:03:11
 */
const { ccclass, property } = cc._decorator

//阵营
export enum campType {
  mine = 1, //自己
  enemy = 2, //敌人
}

//类型
export enum soliderType {
  miner = 0, //矿工
  spearman = 1, //枪兵
  guard = 2, //守卫
  shield = 3, //盾兵
  castle = 4, //城堡

  tree = 5, //资源 树
  mineral = 6, //资源 矿石

  monster = 7, //怪物

  cannon = 8, // 加农炮
  bullet = 9, //子弹 或炮弹
  shell = 10, //地雷

  dl = 11, //地雷二 （采集获得）

  militia = 12, //民兵
  bowman = 13, //弓兵
  swordsman = 14, //剑士
  cavalry = 15, //骑兵
  trapped = 16, //陷阵骑士
  dogs = 17, //训练犬
  master = 18, //法师
  fighter = 19, //格斗家
  scarecrow = 20, // 稻草人
  jumpFire = 21,  //跳跃之火
  logistics = 22, //医疗兵
  warlock = 23, //术士
}

@ccclass

export default class BaseEle extends cc.Component {

  @property({ type: cc.ProgressBar, tooltip: "血条" })
  hpPro: cc.ProgressBar = null;

  @property({ type: cc.Sprite, tooltip: "图片" })
  sp: cc.Sprite = null;

  @property({ type: cc.Animation, tooltip: "动画" })
  ani: cc.Animation = null;

  @property({ type: cc.Animation, tooltip: "着火动画" })
  fireAni: cc.Animation = null;

  @property({ type: cc.Node, tooltip: "冰冻动画" })
  frozenAni: cc.Node = null;

  @property({ type: cc.Node, tooltip: "魔法球" })
  mfBall: cc.Node = null;

  poolName: string = "";

  public centerPos: cc.Node = null; //中心点

  public offX: number = 0;

  public offY: number = 0;

  public targetPosArr: cc.Vec2[] = []; //移动目标数组

  private _nodeIndex: number = 0; //移动目标下标

  private moveSpeed: number = 120; //移动速度

  private speedX: number = 1; //移动倍数

  private _moveAngle: number = 0; //移动角度

  type: soliderType = soliderType.miner; //元素类型

  campType: campType = campType.mine; //阵营类型

  private harvest: number = 0; //收获值
  private attack: number = 0; //攻击力
  hp: number = 0; //生命
  maxHp: number = 0; //最大生命值
  private isCanMove: boolean = true; //是否可移动
  private intval: number = 0; //攻击间隔

  eleId: number = 0;

  ownerId: number = 1;

  public isFly: boolean = false; //飞舞中，不进行碰撞检测

  public isFire: boolean = false; //着火中

  public harvestTime: number = 1; //单位秒

  public musicTime: number = 0;//

  public barrackEny: barrackEntity = null;

  protected onEnable(): void {
    // this.node.pauseAllActions();
  }

  /**
   * 设置数据
   * @param info 
   */
  public setInfo(info) {
    this.eleId = gameCtr.ins.eleId++;
    if (info.id) {
      this.barrackEny = barrackCtr.ins.getBarrackById(info.id);
    }
    this.attack = info.attack || 0;
    this.hp = this.maxHp = info.hp || 0;
    this.harvest = info.harvest || 0;
    this.isCanMove = info.isCanMove || false;
    this.type = info.type;
    this.campType = info.campType || 1;

    this.poolName = info.poolName;
    this.moveSpeed = (info.moveSpeed || 120) * ((this.barrackEny && this.barrackEny.speedXs) || 1);
    this._nodeIndex = info.nodeIndex || 0;
    this.drawHpUi();
    // console.log(this.campType, this.poolName)
    if (this.type == soliderType.castle) {
      createFlyTxt(gameCtr.ins.effectNode, "生命值 +" + helpCtr.ins.extraHp, this.node.x, this.node.y, "#00FF4C")
      this.hp = this.maxHp = (info.hp + helpCtr.ins.extraHp) || 0;
    }

    //随机一友方单位生命值+1
    if (info.id == bagCtr.ins.hpId) {
      createFlyTxt(gameCtr.ins.effectNode, "生命值 +1", this.node.x, this.node.y, "#00FF4C")
      this.hp = this.maxHp = (info.hp + 1) || 0;
    }

    if (this.ani) {
      //让动画播放的不一致
      if (this.type == soliderType.jumpFire) {
        this.ani.play("jump", Math.random() * 20);
      } else {
        this.ani.play("swing", Math.random() * 20);
      }

    }

    if (this.type == soliderType.monster) {
      if (this.fireAni) {
        this.fireAni.node.active = false;
      }

      if (this.frozenAni) {
        this.frozenAni.active = false;
      }
      // this.node.on(cc.Node.EventType.TOUCH_START, this.onClick, this);
    }

    if (this.type == soliderType.shell) {
      let that = this;
      cc.tween(this.node)
        .to(0.2, { y: this.node.y + 60 })
        .call(() => {
          cc.tween(that.node)
            .to(0.1, { y: this.node.y - 40 })
            .start();
        })
        .start();
    }
  }

  /**
   * 设置着火
   */
  setFireAni(url) {
    // this.fireAni.play(url);
    if (url == "fire2") {
      this.fireAni.node.scale = 1;
    } else if (url == "fire4") {
      this.fireAni.node.scaleX = 1.3;
      this.fireAni.node.scaleY = 1.7;
    }
  }

  onClick(e) {
    e.currentTarget.on(cc.Node.EventType.TOUCH_END, this.fly, this);
  }

  fly(e) {
    e.currentTarget.off(cc.Node.EventType.TOUCH_END, this.fly, this);
    e.currentTarget.off(cc.Node.EventType.TOUCH_START, this.fly, this);
    this.doFly();
  }

  doFire(pos) {
    if (this.isFire) return;
    if (this.isFly) return;
    this.isFire = true;
    let that = this;
    this.fireAni.node.active = true;

    let p = this.node.getPosition();
    // console.log(this.node.getPosition(), pos)
    cc.tween(this.node)
      .to(0.6, { x: (p.x + 5 * (p.x - (pos.x - 667))), y: (p.y + 5 * (p.y - (pos.y - 375))) })
      .call(() => {
        that.hp = 0;
        that.recover();
      })
      .start();
  }

  /**
   * 回复血量
   */
  recoverHp(num) {
    if (this.hp < this.maxHp) {
      createFlyTxt(gameCtr.ins.effectNode, "生命值 +" + num, this.node.x, this.node.y, "#00FF4C");
      this.hp += num;
      this.drawHpUi();
    }
  }

  doFly(direction = 1, a = 1) {
    let that = this;
    if (this.isFire) return;
    if (this.isFly) return;
    this.isFly = true;

    cc.tween(this.node)
      .bezierTo(0.3, cc.v2(this.node.x, this.node.y), cc.v2(this.node.x - (Math.random() * 50 + 50) / a * direction, this.node.y + (Math.random() * 100 + 150) / a), cc.v2(this.node.x - (Math.random() * 50 + 100) / a * direction, this.node.y + (Math.random() * 50 + 100) / a))
      .call(() => {
        that.hp = 0;
        that.recover();
      })
      .start();
  }

  /**
   * 绘制皮肤
   * @param url 
   */
  public initSp(url) {
    cc.resources.load(url, cc.SpriteFrame, (err, sp: cc.SpriteFrame) => {
      if (err) return;
      if (!this.sp) return;
      this.sp.spriteFrame = sp;
    })
    // console.log(this.sp.node.height)
  }

  /**
   * 设置下个移动位置
   */
  public setNextPos() {

    switch (this.type) {
      case soliderType.miner:
        this.randCircleMove2();
        break;
      case soliderType.dogs:
        this.randCircleMove();
        break;
      case soliderType.master:
        this.randCircleMove3();
        break;
      case soliderType.warlock:
        this.randCircleMove3();
        break;
      case soliderType.logistics:
        this.randCircleMove3();
        break;
      case soliderType.spearman:
        if (this.targetPosArr.length <= 0) {
          this.targetPosArr = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)];
        }
        // console.log(this.targetPosArr)
        this._nodeIndex = 0;
        break;
      case soliderType.guard:
        this._nodeIndex = 0;

        if (this.centerPos) {
          let centerPos = this.centerPos.getPosition();
          let arr = [cc.v2(-25, 25), cc.v2(-25, -25), cc.v2(25, -25), cc.v2(25, 25)];
          for (let i = 0; i < arr.length; i++) {
            arr[i].x += this.offX + centerPos.x;
            arr[i].y += this.offY + centerPos.y;
          }
          this.targetPosArr = arr;
        } else {
          this.targetPosArr = [];
        }
        break;
      case soliderType.shield:
        if (this.targetPosArr.length <= 0) {
          this.targetPosArr = [cc.v2(0, 0), cc.v2(0, 0)];
        }
        // console.log(this.targetPosArr)
        this._nodeIndex = 0;
        break;
      case soliderType.militia:
        if (this.targetPosArr.length <= 0) {
          this.targetPosArr = [cc.v2(100, 0), cc.v2(0, 0)];
        }
        // console.log(this.targetPosArr)
        this._nodeIndex = 0;
        break;
      case soliderType.bowman:
        this._nodeIndex = 0;

        if (this.centerPos) {
          let centerPos = this.centerPos.getPosition();
          let arr = [cc.v2(-25, 20), cc.v2(-25, -20), cc.v2(25, -20), cc.v2(25, 20)];
          for (let i = 0; i < arr.length; i++) {
            arr[i].x += this.offX + centerPos.x;
            arr[i].y += this.offY + centerPos.y;
          }
          this.targetPosArr = arr;
        } else {
          this.targetPosArr = [];
        }
        break;
      case soliderType.swordsman:
        this._nodeIndex = 0;

        if (this.centerPos) {
          let centerPos = this.centerPos.getPosition();
          let arr = [cc.v2(-30, 25), cc.v2(-30, -25), cc.v2(30, -25), cc.v2(30, 25)];
          for (let i = 0; i < arr.length; i++) {
            arr[i].x += this.offX + centerPos.x;
            arr[i].y += this.offY + centerPos.y;
          }
          this.targetPosArr = arr;
        } else {
          this.targetPosArr = [];
        }
        break;
      case soliderType.cavalry:
        this._nodeIndex = 0;

        if (this.centerPos) {
          let centerPos = this.centerPos.getPosition();
          let arr = [cc.v2(-85, 60), cc.v2(-85, -60), cc.v2(85, -60), cc.v2(85, 60)];
          for (let i = 0; i < arr.length; i++) {
            arr[i].x += this.offX + centerPos.x;
            arr[i].y += this.offY + centerPos.y;
          }
          this.targetPosArr = arr;
        } else {
          this.targetPosArr = [];
        }
        break;
      case soliderType.monster:
        this.hp = 0;
        this.recover();
        break;
      case soliderType.trapped:
        this.hp = 0;
        this.recover();
        break;
      case soliderType.fighter:
        if (this.targetPosArr.length <= 0) {
          this.targetPosArr = [cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0), cc.v2(0, 0)];
        }
        // console.log(this.targetPosArr)
        this._nodeIndex = 0;
        break;
      default:
        this._nodeIndex = 0;
        break;
    }
  }

  /**
 * 设置直线路径
 */
  setLineCom(num) {

    let pos = null;
    switch (num) {
      case 0:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(lineCom).pos1w);
        break;
      case 1:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(lineCom).pos2w);
        break;
    }

    if (pos) {
      pos = cc.v2(pos.x + this.offX, pos.y + this.offY);
    }
    return pos;
  }

  /**
   * 设置三角路径
   */
  setTriangleCom(num) {

    let pos = null;
    switch (num) {
      case 0:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(triangleCom).pos1w);
        break;
      case 1:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(triangleCom).pos2w);
        break;
      case 2:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(triangleCom).pos3w);
        break;
    }

    if (pos) {
      pos = cc.v2(pos.x + this.offX, pos.y + this.offY);
    }
    return pos;
  }

  /**
   * 设置三角路径
   */
  setSquareCom(num) {

    let pos = null;

    switch (num) {
      case 0:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(squareCom).pos1w);
        break;
      case 1:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(squareCom).pos2w);
        break;
      case 2:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(squareCom).pos3w);
        break;
      case 3:
        pos = gameCtr.ins.eleNode.convertToNodeSpaceAR(this.centerPos.getComponent(squareCom).pos4w);
        break;
    }

    if (pos) {
      pos = cc.v2(pos.x + this.offX, pos.y + this.offY);
    }
    return pos;
  }



  /**
   * 以中心点随机创建目标
   */
  randCircleMove() {
    let x = Math.random() * 200 - 100;
    let y = Math.random() * 120 - 70;
    this._nodeIndex = 0;

    if (this.centerPos) {
      let centerPos = this.centerPos.getPosition();
      this.targetPosArr = [cc.v2(x + centerPos.x, y + centerPos.y)];
    } else {
      this.targetPosArr = [];
    }
  }

  /**
   * 以中心点随机创建目标
   */
  randCircleMove2() {
    let x = Math.random() * 150 - 75;
    let y = Math.random() * 90 - 52;
    this._nodeIndex = 0;

    if (this.centerPos) {
      let centerPos = this.centerPos.getPosition();
      this.targetPosArr = [cc.v2(x + centerPos.x, y + centerPos.y)];
    } else {
      this.targetPosArr = [];
    }
  }

  /**
   * 以中心点随机创建目标
   */
  randCircleMove3() {
    let x = Math.random() * 100 - 50;
    let y = Math.random() * 60 - 35;
    this._nodeIndex = 0;

    if (this.centerPos) {
      let centerPos = this.centerPos.getPosition();
      this.targetPosArr = [cc.v2(x + centerPos.x, y + centerPos.y)];
    } else {
      this.targetPosArr = [];
    }
  }

  /**
   * 修改移动倍数
   * @param num 
   */
  setSpeedX(num) {
    this.speedX = num;
  }


  /**
   * 移动
   * @param dt 
   * @returns 
   */
  move(dt) {

    if (!this.isCanMove) return;
    if (this.isFly) return;
    if (this.isFire) return;
    this._moveAngle = 0;
    var nextNode: cc.Vec2 = this.targetPosArr[this._nodeIndex];

    if (this.poolName == "spearman") {

      nextNode = this.setTriangleCom(this._nodeIndex);
      // console.log(nextNode);
    }

    if (this.poolName == "fighter") {

      nextNode = this.setSquareCom(this._nodeIndex);
      // console.log(nextNode);
    }

    if (this.poolName == "shield" || this.poolName == "militia") {

      nextNode = this.setLineCom(this._nodeIndex);
      // console.log(nextNode);
    }

    if (!nextNode) {
      this.setNextPos();
      return;
    };
    var dx: number = nextNode.x - this.node.x;
    var dy: number = nextNode.y - this.node.y;

    var speed: number = this.moveSpeed * this.speedX * dt;

    if (dx * dx + dy * dy > speed * speed) {
      if (this._moveAngle == 0) {
        this._moveAngle = Math.atan2(dy, dx);

        var dire: number = Math.round((-this._moveAngle + Math.PI) / (Math.PI / 4));

      }

      // this.scaleY = 1.5;
      var xspeed: number = Math.cos(this._moveAngle) * speed;
      var yspeed: number = Math.sin(this._moveAngle) * speed;

      if (this.type == soliderType.dogs) {
        //训练犬的采集速度增加50%
        xspeed *= helpCtr.ins.harvestSpeed;
        yspeed *= helpCtr.ins.harvestSpeed;
      }

      if (bagCtr.ins.isSpeedAdd && this.campType == campType.mine) {
        //道具 友方单位加速30%
        xspeed *= bagCtr.ins.speedAdd;
        yspeed *= bagCtr.ins.speedAdd;
      }

      this.node.x += xspeed;
      this.node.y += yspeed;

      if (this.node.x > nextNode.x) {
        this.node.scaleX = 1;
      } else {
        this.node.scaleX = -1;
      }
      this.setZIndex();
    } else {

      this._moveAngle = 0;

      if (this._nodeIndex == this.targetPosArr.length - 1) {

        this.node.x = nextNode.x;

        this.node.y = nextNode.y;

        this.setNextPos();

      } else {
        this._nodeIndex++;
      }
    }
  }

  /**
  * 根据y轴设置 zIndex y轴越大 zIndex 越小
  */
  public setZIndex() {
    if (this.type == soliderType.cannon) {
      this.node.zIndex = 999;
    } else {
      this.node.zIndex = Math.floor(667 - this.node.y);
    }
  }


  /**
   * 掉血
   * @param attk 
   */
  public hurtBlood(attk: number, camp = 1) {
    // console.log(this.hp, "this.hp", attk, this.type)

    if (this.type == soliderType.mineral || this.type == soliderType.tree || this.type == soliderType.dl) {
      this.harvestTime++;

      if (this.harvestTime > 30) {
        this.musicTime++;
        if (this.musicTime > 2) {
          this.musicTime = 0;
          SoundResManager.getInstance().Play("wk");
        }

        this.harvestTime = 0;
        this.hp -= attk;

        if (camp == campType.mine) {

          if (gameCtr.ins.gameModel == modelType.pvp) {

            robotPvpCtr.ins.players.get(gameCtr.ins.roleId).gold += attk;
          } else {
            gameCtr.ins.gold += attk + helpCtr.ins.extraGold;
          }
          // gameCtr.ins.curScene.emit("updateGold");
        } else if (camp == campType.enemy) {
          // aiCtr.ins.gold += attk;
          if (gameCtr.ins.gameModel == modelType.pvp) {
            robotPvpCtr.ins.players.get(gameCtr.ins.roleId * -1).gold += attk;
          }
          // gameCtr.ins.curScene.emit("updateAiGold");
        }
      }
    } else {
      this.hp -= attk;
      if (gameCtr.ins.gameModel == modelType.pvp && this.type == soliderType.castle && robotPvpCtr.ins.players.get(gameCtr.ins.roleId)) {
        console.log("gp", camp)
        if (this.campType == campType.mine) {
          robotPvpCtr.ins.players.get(gameCtr.ins.roleId).hp -= attk;
        } else if (this.campType == campType.enemy) {
          robotPvpCtr.ins.players.get(gameCtr.ins.roleId * -1).hp -= attk;
        }
      }
    }

    if (this.type == soliderType.castle) {
      gameCtr.ins.curScene.emit("doShakeAni");
      if (this.hp <= 0) {
        gameCtr.ins.isOver = true;
        gameCtr.ins.curScene.emit("gameOver");
      }
    }

    this.drawHpUi();
    if (this.hp <= 0) {
      this.recover();
    }
  }

  /**
   * 回收
   */
  public recover() {

    if (!pvpCtr.ins) {

      switch (this.type) {
        case soliderType.miner:
          this.centerPos.getComponent(circleEle).hurtBlood("circle2");
          break;
        case soliderType.dogs:
          this.centerPos.getComponent(circleEle).hurtBlood("circle");
          break;
        case soliderType.master:
          this.centerPos.getComponent(circleEle).hurtBlood("circle3");
          break;
        case soliderType.warlock:
          this.centerPos.getComponent(circleEle).hurtBlood("circle3");
          break;
        case soliderType.spearman:
          this.centerPos.getComponent(triangleCom).hurtBlood();
          break;
        case soliderType.guard:
          this.centerPos.getComponent(circleEle).hurtBlood("circle3");
          break;
        case soliderType.shield:
          this.centerPos.getComponent(lineCom).hurtBlood();
          break;
        case soliderType.bowman:
          this.centerPos.getComponent(circleEle).hurtBlood("circle3");
          break;
        case soliderType.swordsman:
          this.centerPos.getComponent(circleEle).hurtBlood("circle2");
          break;
        case soliderType.militia:
          this.centerPos.getComponent(lineCom).hurtBlood();
          break;
        case soliderType.fighter:
          this.centerPos.getComponent(squareCom).hurtBlood();
          break;
      }
    }

    this.targetPosArr = [];
    this.isFly = false;
    this.isFire = false;
    this._nodeIndex = 0;
    this.hp = 0;

    if (this.fireAni) {
      this.fireAni.node.active = false;
    }
    // this.node.pauseAllActions();

    if (this.node.parent) {
      let wPos = this.node.parent.convertToWorldSpaceAR(this.node.getPosition());
      // console.log("baseEle recover")
      if (this.type == soliderType.monster) {
        //100秒内每击杀一个怪物+1金币（持续100秒）
        if (bagCtr.ins.offerTime > 0) {
          gameCtr.ins.gold += 1;
        }
        gameCtr.ins.curScene.emit("die", wPos);
      }

      if (this.type == soliderType.shell) {
        gameCtr.ins.curScene.emit("baozha", wPos, this.campType);
      }

      if (this.type == soliderType.dl) {
        gameCtr.ins.dlNum--;
        gameCtr.ins.curScene.emit("doShell", null, wPos)
      }

      if (gameCtr.ins.gameModel == modelType.pvp) {

        gameCtr.ins.curScene.emit("die", wPos);

      }
    }

    if (this.type == soliderType.monster) {
      gameCtr.ins.score += 10;
    }

    if (gameCtr.ins.poolObj[this.poolName]) {
      gameCtr.ins.poolObj[this.poolName].put(this.node);
    } else {
      this.node.removeFromParent();
    }
  }

  /**
   * 绘制血条
   */
  public drawHpUi() {
    if (this.hpPro) {
      if (this.hp < this.maxHp) {
        this.hpPro.node.active = true;
        this.hpPro.progress = this.hp / this.maxHp;
      } else {
        this.hpPro.node.active = false;
      }
    }
  }

  /**
   * 碰撞检测
   * @param dt 
   */
  public collision(dt) {

    let childs = [];

    if (this.type == soliderType.miner || this.type == soliderType.dogs) {
      childs = gameCtr.ins.resNode.children;
      childs.forEach(ele => {
        if (ele && ele.getComponent(BaseEle)) {

          if (this.node.getBoundingBox().intersects(ele.getBoundingBox())) {
            ele.getComponent(BaseEle).hurtBlood(this.harvest, this.campType);
          }
        }
      })
    } else {

      childs = gameCtr.ins.eleNode.children;
      childs.forEach(ele => {
        if (ele) {
          let spr = ele.getComponent(BaseEle);
          if (spr) {
            if (spr.campType != this.campType && !this.isFly && !this.isFire && !spr.isFly && !spr.isFire) {
              // console.log(this.type, spr.type, "type1")
              if (this.node.getBoundingBox().intersects(ele.getBoundingBox())) {
                SoundResManager.getInstance().Play("pz");
                spr.hurtBlood(this.attack);
                this.hurtBlood(spr.attack);
                // console.log(this.type, spr.type, "type2", spr.hp, spr.poolName)
              }
            }
          }
        }
      })
    }
  }

  /**
   * 是否在冰冻领域
   */
  public isFrozen() {
    let childs = gameCtr.ins.effectNode.children;
    childs.forEach(ele => {
      if (ele) {
        let spr = ele.getComponent(frozenEle);
        if (spr) {
          if (spr.campType != this.campType) {
            // console.log(this.type, spr.type, "type1")
            if (this.node.getBoundingBox().intersects(ele.getBoundingBox())) {
              if (this.frozenAni)
                this.frozenAni.active = true;
              this.setSpeedX(0);
            }
          }
        }
      }
    })
  }

  hAngle: number = 0;

  /**
   * 帧循环
   * @param dt 
   */
  public onFrameLoop(dt) {
    this.move(dt);
    this.collision(dt);
    this.doAttack(dt);

    this.setSpeedX(1);
    if (this.frozenAni)
      this.frozenAni.active = false;
    this.isFrozen();

    if (this.mfBall && this.type == soliderType.castle) {
      if (helpCtr.ins.isBall) {
        this.mfBall.active = true;
        this.hAngle += 100 * dt;
        let x1 = 0 + 180 * Math.cos(this.hAngle * Math.PI / 180);
        let y1 = 40 + 180 * Math.sin(this.hAngle * Math.PI / 180);
        this.mfBall.setPosition(x1, y1);

        //碰撞检测
        let childs = gameCtr.ins.eleNode.children;
        childs.forEach(ele => {
          if (ele) {
            let spr = ele.getComponent(BaseEle);
            if (spr) {
              if (spr.campType != this.campType && !this.isFly && !this.isFire && !spr.isFly && !spr.isFire) {
                // console.log(this.type, spr.type, "type1")
                if (this.mfBall.getBoundingBox().intersects(ele.getBoundingBox())) {
                  SoundResManager.getInstance().Play("pz");
                  spr.hurtBlood(this.attack);
                  // console.log(this.type, spr.type, "type2", spr.hp, spr.poolName)
                }
              }
            }
          }
        })
      } else {
        this.mfBall.active = false;
      }
    }
  }

  /**
   * 执行攻击
   * @param dt 
   */
  doAttack(dt) {
    // 
    if (!this.barrackEny) return;
    if (!this.barrackEny.gs) return;
    // console.log(Number(this.barrackEny.gs * 60), "Number(this.barrackEny.gs * 60)")
    if (this.type == soliderType.cannon || this.type == soliderType.master) {
      this.intval++;
      if (this.intval > Number(this.barrackEny.gs * 60)) {
        this.intval = 0;

        let targetPos = this.getAreaTarget(this.barrackEny.attackAare);

        if (targetPos) {

          let target = cc.v2(targetPos.x, targetPos.y);
          var deltax: number = target.x - this.node.x
          var deltay: number = target.y - this.node.y;
          let angle = 0;

          if (deltax == 0) {
            if (target.y >= this.node.y) {
              deltax = 0.0000001
            } else {
              deltax = -0.0000001
            }
          }
          if (deltay == 0) {
            if (target.x >= this.node.x) {
              deltay = 0.0000001
            } else {
              deltay = -0.0000001
            }
          }

          if (deltax > 0 && deltay > 0) {
            angle = Math.atan(Math.abs(deltay / deltax))           // 第一项限
          } else if (deltax < 0 && deltay > 0) {
            angle = Math.PI - Math.atan(Math.abs(deltay / deltax))          // 第二项限
          } else if (deltax < 0 && deltay < 0) {
            angle = Math.PI + Math.atan(Math.abs(deltay / deltax))          // 第三项限
          } else {
            angle = 2 * Math.PI - Math.atan(Math.abs(deltay / deltax))         // 第四项限
          }

          if (this.type == soliderType.cannon) {
            gameCtr.ins.curScene.emit("fireBullet", this.node.getPosition(), targetPos, 1, soliderType.cannon, this.campType);
            this.node.angle = angle * 180 / Math.PI + 90 + 180;
          } else if (this.type == soliderType.master) {
            gameCtr.ins.curScene.emit("fireBall", this.node.getPosition(), targetPos, 3, soliderType.master, this.campType);
          }
        }
      }
    } else if (this.type == soliderType.bowman) {
      this.intval++;
      if (this.intval > Number(this.barrackEny.gs * 60)) {
        this.intval = 0;

        let targetPos = this.getAreaTarget(this.barrackEny.attackAare);

        if (targetPos) {

          gameCtr.ins.curScene.emit("fireArrow", this.node.getPosition(), targetPos, 1, soliderType.bowman, this.campType);

        }
      }
    } else if (this.type == soliderType.swordsman) {
      this.intval++;
      if (this.intval > Number(this.barrackEny.gs * 60)) {
        this.intval = 0;
        this.getAreaTarget(this.barrackEny.attackAare, true);
      }
    } else if (this.type == soliderType.fighter) {
      this.intval++;
      if (this.intval > Number(this.barrackEny.gs * 60)) {
        this.intval = 0;
        this.getAreaTarget(this.barrackEny.attackAare, true);
      }
    } else if (this.type == soliderType.logistics) {
      this.intval++;
      if (this.intval > Number(this.barrackEny.gs * 60)) {
        this.intval = 0;
        let targetPos = this.getAreaTarget2(this.barrackEny.attackAare, true);
        if (targetPos)
          gameCtr.ins.curScene.emit("recover", this.node.getPosition(), targetPos, 1, soliderType.master, this.campType);
      }
    } else if (this.type == soliderType.warlock) {
      this.intval++;
      if (this.intval > Number(this.barrackEny.gs * 60)) {
        this.intval = 0;
        let targetPos = this.getAreaTarget(this.barrackEny.attackAare, false);
        if (targetPos)
          gameCtr.ins.curScene.emit("fireSnow", this.node.getPosition(), targetPos, 1, soliderType.warlock, this.campType);
      }
    } else if (this.type == soliderType.scarecrow) {
      this.intval++;
      if (this.intval > Number(this.barrackEny.gs * 60)) {
        this.intval = 0;
        let targetPos = this.getAreaTarget(this.barrackEny.attackAare, false);
        if (targetPos)
          gameCtr.ins.curScene.emit("dc", targetPos, 1, soliderType.scarecrow, this.campType);
      }
    }
  }

  /**
   * 获取离的最近的敌对单位
   */
  getAreaTarget(area: number = 500, isHurt: boolean = false) {
    let childs = gameCtr.ins.eleNode.children;
    let targetPos = null;
    let temp = 1000;
    for (let i = 0; i < childs.length; i++) {
      let ele = childs[i];
      if (ele && ele != this.node) {
        let spr = ele.getComponent(BaseEle);
        if (spr) {
          console.log(spr.campType, this.campType, this.poolName)
          if (spr.campType != this.campType && !spr.isFly && !spr.isFire) {
            let distance = getDistance(this.node.x, this.node.y, ele.x, ele.y);
            if (distance < temp && distance < area) {
              temp = distance;
              targetPos = ele;
            }
          }
        }
      }
    }

    if (isHurt && targetPos) {
      targetPos.getComponent(BaseEle).hurtBlood(this.attack);
    }
    return targetPos && targetPos.getPosition();

  }

  /**
  * 获取离的最近的我方单位
  */
  getAreaTarget2(area: number = 500, isHurt: boolean = false) {
    let childs = gameCtr.ins.eleNode.children;
    let targetPos = null;
    let temp = 1000;
    for (let i = 0; i < childs.length; i++) {
      let ele = childs[i];
      if (ele && ele != this.node) {
        let spr = ele.getComponent(BaseEle);
        if (spr) {
          if (spr.campType == this.campType && !spr.isFly && !spr.isFire) {
            let distance = getDistance(this.node.x, this.node.y, ele.x, ele.y);
            if (distance < temp && distance < area) {
              temp = distance;
              targetPos = ele;
            }
          }
        }
      }
    }

    return targetPos && targetPos.getPosition();

  }

  public isSelf: boolean = false;

  private _targetPos: cc.Vec3 = new cc.Vec3();;

  private _tweens = new TweenPool;

  baseStateId: number;

  /**
   * 同步资源
   * @param state 
   * @param now 
   * @returns 
   */
  updateResState(state: BaseState | ResState, now: number) {
    if (!state) return;

    if (state.hp <= 0) {
      this.recover();
      delete pvpCtr.ins.resBaseEle[this.baseStateId];
      return;
    }
    this.hp = state.hp;
    this.maxHp = state.maxHp;
    this.drawHpUi();
  }

  /**
   * 同步服务器
   * @param state 
   * @param now 
   */
  updateState(state: BaseState | ResState, now: number) {
    if (!state) return;
    if (state.hp <= 0) {
      this.recover();
      delete pvpCtr.ins.baseEles[this.baseStateId];
      return;
    }
    this.hp = state.hp;
    this.drawHpUi();

    this._tweenState(state, now);
    // this.isSelf ? this._resetState(state, now) : this._tweenState(state, now);
    //执行攻击
    if (now > this.intval && this.barrackEny && this.barrackEny.gs && this.isSelf) {
      console.log(this.type);
      this.intval = now + this.barrackEny.gs * 60 * 10;
      let targetPos = null;
      let arrowType = "";
      let deBuffEndTime = 0;
      if (this.poolName == "cannon" || this.poolName == "master") {
        targetPos = this.getAreaTarget(this.barrackEny.attackAare);
        if (this.poolName == "cannon") {
          arrowType = "fireBullet";
        } else if (this.poolName == "master") {
          arrowType = "fireBall";
        }
      } else if (this.poolName == "bowman") {
        targetPos = this.getAreaTarget(this.barrackEny.attackAare);
        arrowType = "fireArrow";
      } else if (this.poolName == "swordsman") {
        targetPos = this.getAreaTarget(this.barrackEny.attackAare);
        arrowType = "bullet";
      } else if (this.poolName == "fighter") {
        targetPos = this.getAreaTarget(this.barrackEny.attackAare);
        arrowType = "bullet";
      } else if (this.poolName == "logistics") {
        targetPos = this.getAreaTarget2(this.barrackEny.attackAare);
        arrowType = "recover";
      } else if (this.poolName == "warlock") {
        targetPos = this.getAreaTarget(this.barrackEny.attackAare);
        arrowType = "fireSnow";
        deBuffEndTime = 3000;
      } else if (this.poolName == "scarecrow") {
        targetPos = this.getAreaTarget(this.barrackEny.attackAare);
        arrowType = "dc";
      }
      console.log("firTimeArrow")
      console.log(targetPos, arrowType);
      if (targetPos && arrowType) {
        //两点之间的距离
        let distance = getDistance(this.node.x, this.node.y, targetPos.x, targetPos.y);
        //飞行时间
        let t = distance / 5 * 10;
        // t = 1000;
        console.log(t, "t");
        // 发送输入
        let wPos = this.node.getPosition();
        pvpCtr.ins.sendClientInput({
          type: 'PlayerAttack',
          arrowType,
          // 显示坐标 —> 逻辑坐标
          targetPos: { x: targetPos.x, y: targetPos.y },
          targetTime: Date.now() + t,
          startPos: { x: wPos.x, y: wPos.y },
          arrowTop: 3,
          baseStateId: this.baseStateId,
          deBuffEndTime
        })
      }
    }
  }

  /**
   * 直接更新位置
   * @param state 
   * @param now 
   */
  private _resetState(state: BaseState | ResState, now: number) {
    //更新位置
    let _targetPos: cc.Vec3 = cc.v3(state.pos.x, state.pos.y);

    if (!this.node.position.equals(_targetPos)) {

      //位置
      this.node.setPosition(_targetPos);

      this.setZIndex();
    }
  }

  /**
   * 插值更新
   * @param state 
   * @param now 
   */
  private _tweenState(state: BaseState | ResState, now: number) {
    //更新位置
    let newPos = cc.v3(state.pos.x, state.pos.y);

    if (!this._targetPos.equals(newPos)) {
      this._tweens.clear();
      this.node.setPosition(this._targetPos);

      //新的位置
      this._targetPos.set(newPos);

      this._tweens.add(cc.tween(this.node).to(1 / gameConfig.syncRate, {
        position: this._targetPos
      }).call(() => {

      }).start());
    }
  }
}

/**
 * 计算两点之间的直线距离
 * @param ownX 
 * @param ownY 
 * @param targetX 
 * @param targetY 
 */
export function getDistance(ownX: number, ownY: number, targetX: number, targetY: number) {

  return Math.sqrt(Math.pow((ownX - targetX), 2) + Math.pow((ownY - targetY), 2));
}
